package com.garbuz.svnadmin.services;

import com.garbuz.svnadmin.AppHelper;
import com.garbuz.svnadmin.FileHelper;
import com.garbuz.svnadmin.SvnModelError;
import com.garbuz.svnadmin.annotations.Service;
import com.garbuz.svnadmin.annotations.ServiceMethod;
import com.garbuz.svnadmin.data.Permission;
import com.garbuz.svnadmin.data.ProcessTO;
import com.garbuz.svnadmin.data.RepoResponse;
import com.garbuz.svnadmin.model.SvnModel;
import common.system.ProcessManager;
import common.system.ProcessRunner;
import common.utils.ArrayUtil;

@Service
public class RepoService extends ServiceBase
{
	private static final Object processLock = new Object();
	
	@ServiceMethod
	public RepoResponse submitPermissions(Object[] repoNames, Object[] permissions) throws Exception
	{
		synchronized (getApp())
		{
			SvnModel model = getApp().readModel();

			for (Object repoName : repoNames)
			{
				model.applyPermissions((String) repoName, ArrayUtil.<Permission>asList(permissions));
			}
			
			getApp().writeModel(model);
		}

		return getRepositoryList();
	}

	@ServiceMethod
	public ProcessTO packRepo(String repoName) throws Exception
	{
		StringBuilder cmdString = new StringBuilder();

		cmdString.append(AppHelper.getShellCommand());
		cmdString.append("ant -q");
		cmdString.append(" -buildfile " + FileHelper.getBackupScriptFile());
		cmdString.append(" -Dproject.name " + repoName);

		ProcessManager manager = getApp().getProcessManager();
		ProcessTO result = new ProcessTO();

		synchronized (processLock)
		{
			if (manager.isRunning())
			{
				result.error = "BUSY";
			}
			else
			{
				manager.execute(cmdString.toString(), repoName);
				result.error = "SUCCESS";
			}

		}

		result.repoName = manager.getDescription();
		return result;
	}

	@ServiceMethod
	public ProcessTO getProcessInfo(Integer position)
	{
		ProcessManager manager = getApp().getProcessManager();

		ProcessTO result = new ProcessTO();
		result.repoName = manager.getDescription();
		result.isRunning = manager.isRunning();
		result.output = manager.getOutputFrom(position);
		result.error = manager.getError();
		result.exitCode = manager.getExitCode();

		return result;
	}

	@ServiceMethod
	public RepoResponse createNewRepo(String repoName) throws Exception
	{
		StringBuilder cmdString = new StringBuilder();
		String repoDir = getApp().getConfig().getSvnRootPath()
				.concat("/")
				.concat(repoName);

		cmdString.append(AppHelper.getShellCommand());
		cmdString.append("svnadmin create ");
		cmdString.append(repoDir);

		ProcessRunner process = new ProcessRunner(cmdString.toString());
		process.run();

		if (process.getExitCode() != 0)
		{
			String output = process.getOutput().concat(process.getError());
			throw new SvnModelError(output);
		}

		if (!AppHelper.isWindowsOS())
		{
			process = new ProcessRunner("chmod -R g+w ".concat(repoDir));
			process.run();
			if (process.getExitCode() != 0)
			{
				String output = process.getOutput().concat(process.getError());
				throw new SvnModelError(output);
			}
		}

		//rewrite model to apply default permission
		synchronized (getApp())
		{
			getApp().writeModel(getApp().readModel());
		}

		return getRepositoryList();
	}

	@ServiceMethod
	public RepoResponse getRepos() throws Exception
	{
		return getRepositoryList();
	}

	private RepoResponse getRepositoryList() throws Exception
	{
		SvnModel model;

		synchronized (getApp())
		{
			model = getApp().readModel();
		}

		RepoResponse response = new RepoResponse();
		response.repos = model.getRepos();
		response.permissions = model.getPossiblePermissions();

		return response;

	}
}
